import os.path
import numpy as np

class Tiler:
    """
    暂时约定以左下角坐标为名字保存文件，例如0_0.data, 0_512.data, 512_0.data。
    grid_binary_file: 网格数据的源文件
    grid_width/grid_height: 网格数量，以经纬度0.01度为一个网格单位的宽高。
    folder_save_to: 生成的文件保存到哪里。
    生成的文件大小总是为512*512
    """
    def __init__(self, grid_binary_file, grid_width, grid_height, folder_save_to="./data/tile"):
        self.grid_binary_file = os.path.abspath(os.path.normpath(grid_binary_file))
        self.grid_width = grid_width
        self.grid_height = grid_height
        self.folder_save_to = os.path.abspath(os.path.normpath(folder_save_to))
        self.size = 512

    def tile(self):
        if self.grid_width < 512 or self.grid_height < 512:
            raise Exception("大小错误，小于分割的大小。")
        # (1) 使用spark生成的二进制文件作为数据源
        with open(self.grid_binary_file, "rb") as f:
            grid = np.fromfile(f, dtype=np.byte, count=self.grid_width * self.grid_height)
        # 1:     1, 2, 3, ...., 3999,4000
        # 2:     1, 2, 3, ...., 3999,4000
        # 3:     1, 2, 3, ...., 3999,4000
        # ......
        # 3000:  1, 2, 3, ...., 3999,4000
        # 共3000行,4000列。对np来说，shape是(3000, 4000)
        matrix = grid.reshape(self.grid_height, self.grid_width)
        print(matrix.shape)

        # 现在开始切蛋糕!(0_0)!
        count_x = self.grid_width // self.size   # x轴方向要切多少次
        x_remains = self.grid_width % self.size # x轴方向上切完是否有多余
        count_y = self.grid_height // self.size # y轴方向要切多少次
        y_remains = self.grid_height % self.size # y轴方向上切完是否有多余

        # 首先处理能完整切出来正方形的区域。
        print("首先处理能完整切出来正方形的区域:")
        for xi in range(0, count_x):
            for yi in range(0, count_y):
                this_grid = matrix[yi*self.size : (yi+1)*self.size, xi*self.size : (xi+1)*self.size]
                file_name = "{}_{}".format(xi*self.size, yi*self.size)
                print("    " + file_name)
                file_name = os.path.join(self.folder_save_to, file_name)
                np.save(file_name, this_grid)

        # 接下来处理上边缘的长条部分。
        if y_remains != 0:
            print("接下来处理上边缘的长条部分:")
            y1, y2 = self.grid_height - self.size, self.grid_height
            for xi in range(0, count_x):
                x1, x2 = xi*self.size, (xi+1)*self.size
                print(x1, x2, y1, y2)
                this_grid = matrix[y1 : y2, x1 : x2]
                file_name = "{}_{}".format(xi * self.size, y1)
                print("    " + file_name)
                file_name = os.path.join(self.folder_save_to, file_name)
                np.save(file_name, this_grid)
            # 右上角的顺便处理了
            if x_remains != 0:
                print("右上角的顺便处理了:")
                x1, x2 = self.grid_width - self.size, self.grid_width
                this_grid = matrix[y1 : y2, x1 : x2]
                file_name = "{}_{}".format(x1, y1)
                print("    " + file_name)
                file_name = os.path.join(self.folder_save_to, file_name)
                np.save(file_name, this_grid)
        # 接下来处理右侧边缘长条部分（除右上角的一块，因为处理上边缘的时候已经处理了）
        if x_remains != 0:
            print("接下来处理右侧边缘长条部分（除右上角的一块，因为处理上边缘的时候已经处理了）:")
            x1, x2 = self.grid_width - self.size, self.grid_width
            for yi in range(0, count_y):
                this_grid = matrix[yi*self.size : (yi+1)*self.size, x1 : x2]
                file_name = "{}_{}".format(x1, yi*self.size)
                print("    " + file_name)
                file_name = os.path.join(self.folder_save_to, file_name)
                np.save(file_name, this_grid)

    def hello(self):
        print("hello from Tiler")



if __name__ == "__main__":
    Tiler("./data/grids.data", 4000, 3000, "./data/tile").tile()